<template>
	<view>
		<view class="content uni-flex-column">
			<CustomNavBar class="navbar" bgColor="#F2F2F2">
				<template v-slot:left>
					<view class="back uni-flex uni-align-center uni-justify-center" @click="goBack">
						<uni-icons type="left" size="20"></uni-icons>
						<image :src="`${$ImgBaseUrl}robot.png`" mode="aspectFill" class="robot"></image>
						<view>小零客服</view>
					</view>
				</template>
			</CustomNavBar>
			<view class="uni-flex-column-center msgBox">
				<scroll-view class="msg-list" scroll-y="true" :scroll-with-animation="scrollAnimation"
					:scroll-top="scrollTop" :scroll-into-view="scrollToView" @scrolltoupper="loadHistory"
					upper-threshold="150" @touchstart="hideDrawer">
					<!-- 加载历史数据waitingUI -->
					<view class="loading" v-if="isHistoryLoading">
						<view class="spinner">
							<view class="rect1"></view>
							<view class="rect2"></view>
							<view class="rect3"></view>
							<view class="rect4"></view>
							<view class="rect5"></view>
						</view>
					</view>
					<view class="row" v-for="(row,index) in noticeList" :key="index" :id="'msg'+row.messageInfo.id">
						<!-- 用户消息 -->
						<block>
							<!-- 自己发出的消息 -->
							<view class="my" v-if="row.senderInfo.userId==userid">
								<view class="left">
									<!-- 文字消息 -->
									<view v-if="row.messageInfo.action=='text'" class="bubble onlyTextBox">
										<rich-text :nodes="row.messageInfo.data.content"></rich-text>
									</view>
									<!-- 协商订单 -->
									<view v-if="row.messageInfo.action=='order_negotiate'" class="bubble orderBox">
										<view class="cardTit">订单信息</view>
										<view class="uni-flex order"
											v-for="item in row.messageInfo.data.negotiateServices" :key="item.itemId">
											<image :src="item?.itemImg" mode="aspectFill"></image>
											<view class="uni-flex-column info">
												<view class="uni-flex uni-align-center uni-justify-between">
													<view class="title">{{ item?.itemName }}</view>
													<view class="price"><text class="unit">¥</text>{{ item?.itemPrice }}
													</view>
												</view>
												<view class="uni-flex uni-align-center uni-justify-between">
													<view class="des">{{ item?.itemDes }}</view>
													<view class="num">x {{ item?.count }}</view>
												</view>
											</view>
										</view>
										<view class="orderbottom">
											<view class="orderno">服务协商编号：{{row.messageInfo.data.negotiateId}}</view>
											<view class="orderprice">待付款<text
													class="unit">¥{{row.messageInfo.data.paymentAmount}}</text><text
													class="total"></text></view>
										</view>
										<view class="btn" @tap="openNegotiateOrderDetail(row.messageInfo.data)">去下单
										</view>
									</view>
									<!-- 平台订单 -->
									<view v-if="row.messageInfo.action=='order_platform'" class="bubble orderBox">
										<view class="cardTit">订单信息</view>
										<view class="uni-flex order"
											v-for="item in row.messageInfo.data.negotiateServices" :key="item.itemId">
											<image :src="item?.itemImg" mode="aspectFill"></image>
											<view class="uni-flex-column info">
												<view class="uni-flex uni-align-center uni-justify-between">
													<view class="title">{{ item?.itemName }}</view>
													<view class="price"><text class="unit">¥</text>{{ item?.itemPrice }}
													</view>
												</view>
												<view class="uni-flex uni-align-center uni-justify-between">
													<view class="des">{{ item?.itemDes }}</view>
													<view class="num">x {{ item?.count }}</view>
												</view>
											</view>
										</view>
										<view class="orderbottom">
											<view class="orderno">订单编号：{{row.messageInfo.data.negotiateId}}</view>
											<view class="orderprice">实付款<text
													class="unit">¥{{row.messageInfo.data.paymentAmount}}</text><text
													class="total"></text></view>
										</view>
									</view>
									<!-- 服务者名片 -->
									<view v-if="row.messageInfo.action=='card'" class="bubble cardBox">
										<view class="cardTit">服务预约</view>
										<view class="uni-flex uni-align-center top">
											<view class="photo-box">
												<image :src="row.senderInfo.avatar" class="photo" />
											</view>
											<view class="uni-flex-column" style="flex: 1">
												<view class="uni-flex uni-align-center uni-justify-between box1">
													<view class="uni-flex">
														<text class="title">{{row.messageInfo.data.name}}</text>
														<view class="real-name">
															<image :src="`${$ImgBaseUrl}findpeople_realname.png`"
																mode="widthFix" />
															<text
																class="text1">{{row.messageInfo.data.realName===true?'已实名':'未实名'}}</text>
														</view>
													</view>
												</view>
												<view class="box2">
													<text
														class="text1">{{row.messageInfo.data.sex==="0"?'男':row.messageInfo.data.sex==="1"?'女':'未知'}}
														| {{row.messageInfo.data.age}}岁 | </text>
													<text class="text2">{{row.messageInfo.data.comEvaluation}}分</text>
												</view>
											</view>
										</view>
										<view class="uni-flex box3">
											<text class="text1">接单数: {{ row.messageInfo.data.closeCount }}单 | 好评数:
												{{ row.messageInfo.data.positiveReviews }}单</text>
										</view>

										<view class="uni-flex box3">
											<text class="text1">擅长服务: </text>
											<view class="con">
												<!-- 判断 goodServices 是否有数据 -->
												<template
													v-if="row.messageInfo.data.goodServices && row.messageInfo.data.goodServices.length > 0">
													<view v-for="(item, index) in row.messageInfo.data.goodServices"
														:key="index" class="project">
														{{ item }}
													</view>
												</template>
												<template v-else>
													<view class="empty-text">暂无</view>
												</template>
											</view>
										</view>
										<view class="footer uni-flex uni-align-center uni-justify-between">
											<view class="btn" @click="goToContact(row.messageInfo.data)">获取联系方式</view>
											<view class="btn">查看详情</view>
										</view>
									</view>
									<!-- 地址 -->
									<view class="addressBox" v-if="row.messageInfo.action=='address'"
										@tap="goToLocation(row.messageInfo.data)">
										<map id="map" :latitude="row.messageInfo.data.lat"
											:longitude="row.messageInfo.data.lng" :scale="15" class="map-container"
											:enable-scroll="false" :enable-zoom="false"
											:markers="[{id: 1,latitude: row.messageInfo.data.lat, longitude: row.messageInfo.data.lng,width: 16,height: 20,}]"
											@tap="goToLocation(row.messageInfo.data)">
										</map>
										<view class="address-text">
											<view class="name">{{ row.messageInfo.data.name }}</view>
											<view class="address">{{ row.messageInfo.data.address }}</view>
										</view>
									</view>
								</view>
								<view class="right">
									<image :src="row.senderInfo.avatar"></image>
								</view>
							</view>
							<!-- 别人发出的消息 -->
							<view class="other" v-else>
								<!-- 左-头像 -->
								<view class="left">
									<image :src="row.senderInfo.avatar"></image>
								</view>
								<!-- 右-用户名称-时间-消息 -->
								<view class="right">
									<!-- 文字消息 -->
									<view v-if="row.messageInfo.action=='text'" class="bubble onlyTextBox">
										<rich-text :nodes="row.messageInfo.data.content"></rich-text>
									</view>
									<!-- 协商订单 -->
									<view v-if="row.messageInfo.action=='order_negotiate'" class="bubble orderBox">
										<view class="cardTit">订单信息</view>
										<view class="uni-flex order"
											v-for="item in row.messageInfo.data.negotiateServices" :key="item.itemId">
											<image :src="item?.itemImg" mode="aspectFill"></image>
											<view class="uni-flex-column info">
												<view class="uni-flex uni-align-center uni-justify-between">
													<view class="title">{{ item?.itemName }}</view>
													<view class="price"><text class="unit">¥</text>{{ item?.itemPrice }}
													</view>
												</view>
												<view class="uni-flex uni-align-center uni-justify-between">
													<view class="des">{{ item?.itemDes }}</view>
													<view class="num">x {{ item?.count }}</view>
												</view>
											</view>
										</view>
										<view class="orderbottom">
											<view class="orderno">服务协商编号：{{row.messageInfo.data.negotiateId}}</view>
											<view class="orderprice">待付款<text
													class="unit">¥{{row.messageInfo.data.paymentAmount}}</text><text
													class="total"></text></view>
										</view>
										<view class="btn" @tap="openNegotiateOrderDetail(row.messageInfo.data)">去下单
										</view>
									</view>
									<!-- 平台订单 -->
									<view v-if="row.messageInfo.action=='order_platform'" class="bubble orderBox">
										<view class="cardTit">订单信息</view>
										<view class="uni-flex order"
											v-for="item in row.messageInfo.data.negotiateServices" :key="item.itemId">
											<image :src="item?.itemImg" mode="aspectFill"></image>
											<view class="uni-flex-column info">
												<view class="uni-flex uni-align-center uni-justify-between">
													<view class="title">{{ item?.itemName }}</view>
													<view class="price"><text class="unit">¥</text>{{ item?.itemPrice }}
													</view>
												</view>
												<view class="uni-flex uni-align-center uni-justify-between">
													<view class="des">{{ item?.itemDes }}</view>
													<view class="num">x {{ item?.count }}</view>
												</view>
											</view>
										</view>
										<view class="orderbottom">
											<view class="orderno">订单编号：{{row.messageInfo.data.negotiateId}}</view>
											<view class="orderprice">实付款<text
													class="unit">¥{{row.messageInfo.data.paymentAmount}}</text><text
													class="total"></text></view>
										</view>
									</view>
									<!-- 服务者名片 -->
									<view v-if="row.messageInfo.action=='card'" class="bubble cardBox">
										<view class="cardTit">服务预约</view>
										<view class="uni-flex uni-align-center top">
											<view class="photo-box">
												<image :src="row.senderInfo.avatar" class="photo" />
											</view>
											<view class="uni-flex-column" style="flex: 1">
												<view class="uni-flex uni-align-center uni-justify-between box1">
													<view class="uni-flex">
														<text class="title">{{row.messageInfo.data.name}}</text>
														<view class="real-name">
															<image :src="`${$ImgBaseUrl}findpeople_realname.png`"
																mode="widthFix" />
															<text
																class="text1">{{row.messageInfo.data.realName===true?'已实名':'未实名'}}</text>
														</view>
													</view>
												</view>
												<view class="box2">
													<text
														class="text1">{{row.messageInfo.data.sex==="0"?'男':row.messageInfo.data.sex==="1"?'女':'未知'}}
														| {{row.messageInfo.data.age}}岁 | </text>
													<text class="text2">{{row.messageInfo.data.comEvaluation}}分</text>
												</view>
											</view>
										</view>
										<view class="uni-flex box3">
											<text class="text1">接单数: {{ row.messageInfo.data.closeCount }}单 | 好评数:
												{{ row.messageInfo.data.positiveReviews }}单</text>
										</view>
										<view class="uni-flex box3">
											<text class="text1">擅长服务: </text>
											<view class="con">
												<template
													v-if="row.messageInfo.data.goodServices && row.messageInfo.data.goodServices.length > 0">
													<view v-for="(item, index) in row.messageInfo.data.goodServices"
														:key="index" class="project">
														{{ item }}
													</view>
												</template>
												<template v-else>
													<view class="empty-text">暂无</view>
												</template>
											</view>
										</view>
										<view class="footer uni-flex uni-align-center uni-justify-between">
											<view class="btn">获取联系方式</view>
											<view class="btn">查看详情</view>
										</view>
									</view>
									<!-- 地址 -->
									<view class="addressBox" v-if="row.messageInfo.action=='address'"
										@tap="goToLocation(row.messageInfo.data)">
										<map id="map" :latitude="row.messageInfo.data.lat"
											:longitude="row.messageInfo.data.lng" :scale="15" class="map-container"
											:enable-scroll="false" :enable-zoom="false"
											:markers="[{id: 1,latitude: row.messageInfo.data.lat, longitude: row.messageInfo.data.lng,width: 16,height: 20,}]"
											@tap="goToLocation(row.messageInfo.data)">
										</map>
										<view class="address-text">
											<view class="name">{{ row.messageInfo.data.name }}</view>
											<view class="address">{{ row.messageInfo.data.address }}</view>
										</view>
									</view>
								</view>
							</view>
						</block>
					</view>
				</scroll-view>
				<!--录音UI效果-->
				<view class="record" :class="recording?'':'hidden'">
					<view class="ing" :class="willStop?'hidden':''">
						<view class="icon luyin2"></view>
					</view>
					<view class="cancel" :class="willStop?'':'hidden'">
						<view class="icon chehui"></view>
					</view>
					<view class="tis" :class="willStop?'change':''">{{recordTis}}</view>
				</view>
			</view>
			<!-- 指令框 -->
			<view class="instruction-box uni-flex uni-align-center">
				<view class="instruction-item">更换服务人员</view>
				<view class="instruction-item">显示快捷指令</view>
				<view class="instruction-item">快捷指令</view>
			</view>
			<view class="input-box" :class="popupLayerClass" @touchmove.stop.prevent>
				<view class="voice">
					<view @tap="switchVoice">
						<image class="EmojiIcon"
							:src="isVoice?`${$ImgBaseUrl}chatinputicon3.png`:`${$ImgBaseUrl}chatinputicon1.png`"
							mode="scaleToFill" />
					</view>
				</view>
				<view class="textbox">
					<view class="voice-mode" :class="[isVoice?'':'hidden',recording?'recording':'']"
						@touchstart="voiceBegin" @touchmove.stop.prevent="voiceIng" @touchend="voiceEnd"
						@touchcancel="voiceCancel">{{voiceTis}}</view>
					<view class="text-mode" :class="isVoice?'hidden':''">
						<view class="box">
							<textarea class="input" auto-height="true" confirm-type="send" type="text"
								placeholder="请输入消息..." :maxlength="-1" :adjust-position="false" v-model="textMsgCon"
								confirm-hold :show-confirm-bar="false" @input="input" @confirm="sendMsg"
								@focus="textareaFocus" @keyboardheightchange="keyboardheightchange" />
						</view>
					</view>
				</view>
				<view class="more" @tap="chooseEmoji">
					<image class="EmojiIcon" :src="`${$ImgBaseUrl}chatinputicon2.png`" mode="scaleToFill" />
				</view>
				<view class="more" @tap.stop.prevent="showMore">
					<uni-icons :type="!hideMore?'close':'plus'" size="30"></uni-icons>
				</view>
			</view>
			<!-- 键盘高度 -->
			<view class="keyboard" :style="{ height: keyboardHeight + 'px' }"></view>
			<!-- 抽屉栏 -->
			<view class="popup-layer" :class="popupLayerClass" @touchmove.stop.prevent="discard">
				<!-- 表情 -->
				<swiper class="emoji-swiper" :class="{hidden:hideEmoji}" indicator-dots="true" duration="150">
					<!-- <swiper-item v-for="(page,pid) in emojiList" :key="pid">
						<view v-for="(em,eid) in page" :key="eid" @tap="addEmoji(em)">
							<image mode="widthFix" :src="'@/static/img/emoji/'+em.url"></image>
						</view>
					</swiper-item> -->
				</swiper>
				<!-- 更多功能 相册-拍照-地址 -->
				<view class="more-layer" :class="{hidden:hideMore}">
					<view class="list">
						<view class="box" @tap="chooseImage">
							<view class="image">
								<image class="imageIcon" style="height: 33rpx;" :src="`${$ImgBaseUrl}chatlabel2.png`"
									mode="scaleToFill" />
							</view>
							<view class="text">图片</view>
						</view>
						<view class="box" @tap="camera">
							<view class="image">
								<image class="imageIcon" style="height: 37rpx;" :src="`${$ImgBaseUrl}chatlabel1.png`"
									mode="scaleToFill" />
							</view>
							<view class="text">拍照</view>
						</view>
						<view class="box" @tap="selectAddress">
							<view class="image">
								<image class="imageIcon" :src="`${$ImgBaseUrl}chatlabel3.png`" mode="scaleToFill" />
							</view>
							<view class="text">发送位置</view>
						</view>
					</view>
				</view>
			</view>
		</view>
		<CallDialog :showDialog="showCallDialog" :phoneNumber="phoneNumber" @close="showCallDialog = false">
		</CallDialog>
	</view>
</template>
<script setup>
	import CustomNavBar from "@/components/custom-navbar/index.vue";
	import CallDialog from '@/components/CallDialog.vue'
	import {
		ref,
		onMounted,
		onUnmounted,
		nextTick
	} from "vue";
	import WebSocketService from '@/utils/WebSocketService.js';
	import {
		WebSocketUrl
	} from "@/utils/domain.js";
	import {
		createOrder
	} from '@/api/serviceNegotiate.js';
	import {
		getUserEncryption
	} from '@/api/findPeople.js'
	// WebSocket 状态和通知列表
	const wsOpen = ref(false);
	const textMsgCon = ref('');
	const noticeList = ref([]);
	const userid = ref(0);
	const peerid = ref(0);
	const showCallDialog = ref(false)
	const phoneNumber = ref(''); // 初始默认号码
	const peerAvatarImg = ref('');
	const userAvatar = ref('');
	const type = ref('');
	const peername = ref('');
	//定义
	//消息列表
	const isHistoryLoading = ref(false);
	const scrollAnimation = ref(false);
	const scrollTop = ref(0);
	const pageNum = ref(1);
	const pageSize = ref(100);
	const scrollToView = ref('');
	const msgList = ref([]);
	const msgImgList = ref([]);
	const myuid = ref(0);
	const RECORDER = uni.getRecorderManager();
	const isVoice = ref(false);
	const voiceTis = ref('按住 说话');
	const recordTis = ref("手指上滑 取消发送");
	const recording = ref(false);
	const willStop = ref(false);
	const initPoint = ref({
		identifier: 0,
		Y: 0
	});
	const recordTimer = ref(null);
	const recordLength = ref(0);
	const keyboardHeight = ref(0);
	//播放语音相关参数
	const AUDIO = uni.createInnerAudioContext();
	const playMsgid = ref(null);
	const VoiceTimer = ref(null);
	// 抽屉参数
	const popupLayerClass = ref('');
	// more参数
	const hideMore = ref(true);
	//表情定义
	const hideEmoji = ref(true);
	const emojiList = ref([]);
	const onlineEmoji = ref({});
	const usertype = ref('');

	// WebSocket 连接实例
	const wsService = new WebSocketService(WebSocketUrl);
	onMounted(() => {
		const pages = getCurrentPages();
		const currentPage = pages[pages.length - 1];
		const query = currentPage.options;
		const {
			peerId,
			userId,
			peerAvatar,
			actionType,
			peerNikeName
		} = query;
		userid.value = Number(userId);
		peerid.value = Number(peerId);
		peerAvatarImg.value = peerAvatar;
		type.value = actionType;
		peername.value = peerNikeName;
		userAvatar.value = uni.getStorageSync('user_info') ? JSON.parse(uni.getStorageSync('user_info')).avatar :
			'';
		usertype.value = uni.getStorageSync('user_info') ? JSON.parse(uni.getStorageSync('user_info')).userType :
			'';
		inintWebSocket();
		//语音自然播放结束
		console.log(AUDIO)
		AUDIO.onEnded((res) => {
			playMsgid.value = null;
		});
		// #ifndef H5
		//录音开始事件
		RECORDER.onStart((e) => {
			recordBegin(e);
		})
		//录音结束事件
		RECORDER.onStop((e) => {
			recordEnd(e);
		})
		// #endif
		scrollTop.value = 9999999;
		console.log(scrollTop.value)
	});

	onUnmounted(() => {
		console.log('页面卸载了')
		wsService.onDestroy();
	});

	// 初始化 WebSocket
	const inintWebSocket = () => {
		wsService.init();

		// 监听消息
		wsService.onMessage((data) => {
			// console.log('页面收到消息：', data);
			const message = JSON.parse(data);
			if (message.status === 'connect') {
				sendOpen();
			} else if (message.status === 'open') {
				if (message.pageNum === 1) {
					noticeList.value.push(...message.rows);
					scrollToBottom();
				} else {
					isHistoryLoading.value = false;
					scrollAnimation.value = true; //恢复滚动动画
					noticeList.value.unshift(...message.rows);
				}
			} else if (message.status === 'message') {
				const msg = {
					messageInfo: message.messageInfo,
					receiveInfo: message.receiveInfo,
					senderInfo: message.senderInfo
				}
				noticeList.value.push(msg);
				scrollToBottom();
			}
		});

		// 监听连接打开
		wsService.onOpen(() => {
			console.log('页面监听到打开');
			const message = {
				"status": "connect",
				"authentication": uni.getStorageSync('access_token'),
				"channel": "CHANNEL_MOBILE"
			};
			wsService.sendMessage(message);
		});

		// 监听连接关闭
		wsService.onClose(() => {
			console.log('WebSocket连接已关闭');
		});

		// 监听错误
		wsService.onError((err) => {
			console.error('WebSocket连接错误', err);
		});
	};
	// 发送文字消息
	const sendMsg = () => {
		console.log('发送消息');
		if (textMsgCon.value.trim() !== '') {
			const message = {
				"senderInfo": {
					"userId": userid.value,
				},
				"receiveInfo": {
					"userId": peerid.value,
				},
				"messageInfo": {
					"action": "text",
					"data": {
						"content": textMsgCon.value
					},
					"state": "0",
				},
				"authentication": uni.getStorageSync('access_token'),
				"channel": "CHANNEL_MOBILE",
				"status": "message",
			};
			wsService.sendMessage(message);
			textMsgCon.value = '';
		}
	};

	// 根据type发送status为open的消息：type:card发送名片
	const sendOpen = () => {
		console.log('第一次进来发送消息: ' + type.value);
		const message = {
			"senderInfo": {
				"userId": userid.value,
			},
			"receiveInfo": {
				"userId": peerid.value,
			},
			"messageInfo": {
				"action": '',
			},
			"pageParam": {
				"pageNum": pageNum.value,
				"pageSize": pageSize.value
			},
			"authentication": uni.getStorageSync('access_token'),
			"channel": "CHANNEL_MOBILE",
			"status": "open",
		};
		wsService.sendMessage(message);
	};

	// 发送地址
	const sendAddress = (longitude, latitude, address, name) => {
		const message = {
			"senderInfo": {
				"userId": userid.value,
			},
			"receiveInfo": {
				"userId": peerid.value,
			},
			"messageInfo": {
				"action": 'address',
				"data": {
					"lng": longitude,
					"lat": latitude,
					"address": address,
					"name": name
				},
			},
			"pageParam": {
				"pageNum": pageNum.value,
				"pageSize": pageSize.value
			},
			"authentication": uni.getStorageSync('access_token'),
			"channel": "CHANNEL_MOBILE",
			"status": "message",
		};
		wsService.sendMessage(message);

	};

	// 返回
	const goBack = () => {
		uni.navigateBack({
			delta: 1
		})
	};
	// 监听键盘高度变化
	const keyboardheightchange = (e) => {
		if (e.detail.duration > 0) {
			scrollToBottom();
		}
		keyboardHeight.value = e.detail.height;
	};
	// 接受消息(筛选处理)
	const screenMsg = (msg) => {
		nextTick(() => {
			// 滚动到底
			scrollToView.value = 'msg' + msg.msg.id
		});
	};

	//触发滑动到顶部(加载历史信息记录)
	const loadHistory = (e) => {
		console.log('加载历史信息记录')
		if (isHistoryLoading.value) {
			return;
		}
		isHistoryLoading.value = true; //参数作为进入请求标识，防止重复请求
		scrollAnimation.value = false; //关闭滑动动画
		pageNum.value = pageNum.value + 1; //页码+1
		sendOpen(); //发送open消息
	};
	const scroll = (e) => {
		scrollTop.value = e.detail.scrollTop;
	};
	//处理图片尺寸，如果不处理宽高，新进入页面加载图片时候会闪
	const setPicSize = (content) => {
		// 让图片最长边等于设置的最大长度，短边等比例缩小，图片控件真实改变，区别于aspectFit方式。
		let maxW = uni.rpx2px(350); //350是定义消息图片最大宽度
		let maxH = uni.rpx2px(350); //350是定义消息图片最大高度
		if (content.w > maxW || content.h > maxH) {
			let scale = content.w / content.h;
			content.w = scale > 1 ? maxW : maxH * scale;
			content.h = scale > 1 ? maxW / scale : maxH;
		}
		return content;
	};
	//更多功能(点击+弹出) 
	const showMore = () => {
		isVoice.value = false;
		hideEmoji.value = true;
		if (hideMore.value) {
			hideMore.value = false;
			console.log('1dakai', hideMore.value)
			openDrawer();
			scrollToBottom();
		} else {
			console.log('1guanbi', hideMore.value)
			hideDrawer();
		}
	};
	// 打开抽屉
	const openDrawer = () => {
		popupLayerClass.value = 'showLayer';
	};
	// 隐藏抽屉
	const hideDrawer = () => {
		popupLayerClass.value = '';
		setTimeout(() => {
			hideMore.value = true;
			console.log('2dakai', hideMore.value)
			hideEmoji.value = true;
		}, 150);
	};
	// 选择图片发送
	const chooseImage = () => {
		getImage('album');
	};
	//拍照发送
	const camera = () => {
		getImage('camera');
	};
	//选照片 or 拍照
	const getImage = (type) => {
		hideDrawer();
		uni.chooseImage({
			sourceType: [type],
			sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图，默认二者都有
			success: (res) => {
				for (let i = 0; i < res.tempFilePaths.length; i++) {
					uni.getImageInfo({
						src: res.tempFilePaths[i],
						success: (image) => {
							console.log(image.width);
							console.log(image.height);
							let msg = {
								url: res.tempFilePaths[i],
								w: image.width,
								h: image.height
							};
							sendMsg(msg, 'img');
						}
					});
				}
			}
		});
	};
	// 选择表情
	const chooseEmoji = () => {
		hideMore.value = true;
		console.log('3dakai', hideMore.value)
		if (hideEmoji.value) {
			hideEmoji.value = false;
			openDrawer();
		} else {
			hideDrawer();
		}
	};
	//获取焦点，如果不是选表情ing,则关闭抽屉
	const textareaFocus = () => {
		console.log('4dakai', hideMore.value)
		// if(this.popupLayerClass=='showLayer' && this.hideMore == false){
		// 	this.hideDrawer();
		// }
	};
	// 发送文字消息
	const sendText = () => {
		console.log('9')
		hideDrawer(); //隐藏抽屉
		if (!textMsg.value) {
			return;
		}
		let content = replaceEmoji(textMsg.value);
		let msg = {
			text: content
		}
		sendMsg(msg, 'text');
		textMsg.value = ''; //清空输入框
	};
	//替换表情符号为图片
	const replaceEmoji = (str) => {
		let replacedStr = str.replace(/\[([^(\]|\[)]*)\]/g, (item, index) => {
			console.log("item: " + item);
			for (let i = 0; i < emojiList.value.length; i++) {
				let row = emojiList.value[i];
				for (let j = 0; j < row.length; j++) {
					let EM = row[j];
					if (EM.alt == item) {
						//在线表情路径，图文混排必须使用网络路径，请上传一份表情到你的服务器后再替换此路径 
						//比如你上传服务器后，你的100.gif路径为https://www.xxx.com/emoji/100.gif 则替换onlinePath填写为https://www.xxx.com/emoji/
						let onlinePath = 'https://s2.ax1x.com/2019/04/12/'
						let imgstr = '<img src="' + onlinePath + this.onlineEmoji[EM.url] + '">';
						console.log("imgstr: " + imgstr);
						return imgstr;
					}
				}
			}
		});
		return '<div style="display: flex;align-items: center;word-wrap:break-word;">' + replacedStr + '</div>';
	};
	// 预览图片
	const showPic = (msg) => {
		uni.previewImage({
			indicator: "none",
			current: msg.content.url,
			urls: msgImgList.value
		});
	};
	// 播放语音
	const playVoice = (msg) => {
		playMsgid.value = msg.id;
		AUDIO.src = msg.content.url;
		nextTick(() => {
			AUDIO.play();
		});
	};
	// 录音开始
	const voiceBegin = (e) => {
		console.log(e)
		if (e.touches.length > 1) {
			return;
		}
		initPoint.value.Y = e.touches[0].clientY;
		initPoint.value.identifier = e.touches[0].identifier;
		RECORDER.start({
			format: "mp3"
		}); //录音开始,
	};
	//录音开始UI效果
	const recordBegin = (e) => {
		recording.value = true;
		voiceTis.value = '松开 结束';
		recordLength.value = 0;
		recordTimer.value = setInterval(() => {
			recordLength.value++;
		}, 1000)
	};
	// 录音被打断
	const voiceCancel = () => {
		recording.value = false;
		voiceTis.value = '按住 说话';
		recordTis.value = '手指上滑 取消发送'
		willStop.value = true; //不发送录音
		RECORDER.stop(); //录音结束
	};
	// 录音中(判断是否触发上滑取消发送)
	const voiceIng = (e) => {
		if (!recording.value) {
			return;
		}
		let touche = e.touches[0];
		//上滑一个导航栏的高度触发上滑取消发送
		if (initPoint.value.Y - touche.clientY >= uni.rpx2px(100)) {
			willStop.value = true;
			recordTis.value = '松开手指 取消发送'
		} else {
			willStop.value = false;
			recordTis.value = '手指上滑 取消发送'
		}
	};
	// 结束录音
	const voiceEnd = (e) => {
		if (!recording.value) {
			return;
		}
		recording.value = false;
		voiceTis.value = '按住 说话';
		recordTis.value = '手指上滑 取消发送'
		RECORDER.stop(); //录音结束
	};
	//录音结束(回调文件)
	const recordEnd = (e) => {
		clearInterval(recordTimer.value);
		if (!willStop.value) {
			console.log("e: " + JSON.stringify(e));
			let msg = {
				length: 0,
				url: e.tempFilePath
			}
			let min = parseInt(recordLength.value / 60);
			let sec = recordLength.value % 60;
			min = min < 10 ? '0' + min : min;
			sec = sec < 10 ? '0' + sec : sec;
			msg.length = min + ':' + sec;
			sendMsg(msg, 'voice');
		} else {
			console.log('取消发送录音');
		}
		willStop.value = false;
	};
	// 切换语音/文字输入
	const switchVoice = () => {
		console.log('8')
		hideDrawer();
		isVoice.value = isVoice.value ? false : true;
	};
	const discard = () => {
		return;
	};
	// 滑动页面到最底端
	const scrollToBottom = () => {
		++scrollTop.value;
	};
	// 选择地址并发送
	const selectAddress = () => {
		uni.navigateTo({
			url: "/pages/tabBars/serviceAddress/selectMap",
			events: {
				// 定义接收事件
				acceptDataFromPageB: (data) => {
					console.log('选择完地址了', data)
					const dataInit = data.message;
					const [longitude, latitude] = dataInit.location.split(',');
					sendAddress(longitude, latitude, dataInit.address, dataInit.name);
				},
			},
			success: (res) => {
				// 发送初始数据（可选）
				res.eventChannel.emit("sendDataToPageB", {
					initData: {},
				});
			},
		});
	};
	// 查看地图
	const goToLocation = (e) => {
		uni.openLocation({
			latitude: Number(e.lat),
			longitude: Number(e.lng),
			scale: 18,
			name: e.name,
			address: e.address,
		});
	};
	// 发起服务协商
	const openNegotiateOrder = () => {
		uni.navigateTo({
			url: `/pages/order/serviceNegotiate/index?peerid=${peerid.value}`,
		});
	};
	// 查看服务协商订单详情
	const openNegotiateOrderDetail = async (item) => {
		const username = uni.getStorageSync('user_info') ? JSON.parse(uni.getStorageSync('user_info')).nikeName :
			'';
		const res = await createOrder(item);
		console.log(res)
		if (res.code === 200) {
			uni.navigateTo({
				url: "/pages/order/consumerOrder/placeOrder?id=" + res.data.id
				// url: "/pages/order/serviceNegotiate/detail?orderId=" + res.data.id+"&username="+username,
			});
		}
	};
	// 获取联系方式
	const goToContact = async (data) => {
		console.log(data)
		if (data.userId === userid.value) {
			uni.showToast({
				title: '不能联系自己哦~',
				icon: 'none'
			})
		} else {
			showCallDialog.value = true
			try {
				const res = await getUserEncryption(data.userId);
				console.log('获取加密号码接口返回', res);
				if (res.code === 200) {
					phoneNumber.value = res.data
				}
				// 假设接口返回的加密号码字段是 encryptionPhone，根据实际接口调整

			} catch (err) {
				console.error('获取加密号码失败', err);
			}
		}
	};
</script>
<style lang="scss">
	@font-face {
		font-family: "HMfont-home";
		src: url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2');
	}

	.icon {
		font-family: "HMfont-home" !important;
		font-size: 56upx;
		font-style: normal;
		color: #333;

		&.chehui:before {
			content: "\e904";
		}

		&.luyin2:before {
			content: "\e677";
		}

		&.other-voice:before {
			content: "\e667";
		}

		&.my-voice:before {
			content: "\e906";
		}

		&.close:before {
			content: "\e607";
		}
	}

	.hidden {
		display: none !important;
	}

	.popup-layer {
		&.showLayer {
			display: block;
		}

		display: none;
		transition: all .15s linear;
		width: 96%;
		height: 42vw;
		padding: 40rpx 2% 0;
		background-color: #fff;
		// position: fixed;
		z-index: 20;

		// top: 100%;
		.emoji-swiper {
			height: 40vw;

			swiper-item {
				display: flex;
				align-content: flex-start;
				flex-wrap: wrap;

				view {
					width: 12vw;
					height: 12vw;
					display: flex;
					justify-content: center;
					align-items: center;

					image {
						width: 8.4vw;
						height: 8.4vw;
					}
				}
			}
		}

		.more-layer {
			width: 100%;
			height: 42vw;

			.list {
				width: 100%;
				display: flex;
				flex-wrap: wrap;
				padding-left: 64rpx;

				.box {
					width: 96rpx;
					margin: 0 92rpx 0 0;
					display: flex;
					flex-direction: column;
					justify-content: center;
					align-items: center;

					.image {
						width: 87rpx;
						height: 87rpx;
						background: #FFFFFF;
						border-radius: 20rpx;
						opacity: 0.6;
						display: flex;
						justify-content: center;
						align-items: center;
						margin-bottom: 20rpx;

						.imageIcon {
							width: 41rpx;
							height: 40rpx;
						}
					}

					.text {
						font-weight: 400;
						font-size: 24rpx;
						color: #666666;
						line-height: 33rpx;
					}
				}
			}
		}
	}

	.instruction-box {
		background-color: transparent;
		padding: 9rpx 0;

		.instruction-item {
			padding: 8rpx 18rpx;
			background-color: #FFFFFF;
			border-radius: 24rpx;
			font-weight: 400;
			font-size: 24rpx;
			color: #303133;
			margin-left: 24rpx;
		}
	}

	.input-box {
		width: 98%;
		padding: 0 1% env(safe-area-inset-bottom);
		background-color: #fff;
		display: flex;
		// position: fixed;
		z-index: 20;

		// bottom:0;
		&.showLayer {}

		transition: all .15s linear;

		.voice {
			flex-shrink: 0;
			width: 85rpx;
			height: 100rpx;
			display: flex;
			justify-content: center;
			align-items: center;
		}

		.more {
			flex-shrink: 0;
			width: 60rpx;
			height: 100rpx;
			display: flex;
			justify-content: center;
			align-items: center;
		}

		.EmojiIcon {
			width: 46rpx;
			height: 46rpx;
		}

		.send {
			//H5发送按钮左边距
			/* #ifdef H5 */
			margin-left: 20rpx;
			/* #endif */
			flex-shrink: 0;
			width: 100rpx;
			height: 100rpx;
			display: flex;
			align-items: center;

			.btn {
				width: 90rpx;
				height: 56rpx;
				display: flex;
				justify-content: center;
				align-items: center;
				background: linear-gradient(to right, #f09b37, #eb632c);
				color: #fff;
				border-radius: 6rpx;
				font-size: 24rpx;
			}
		}

		.textbox {
			width: 100%;
			min-height: 70rpx;
			margin-top: 15rpx;

			.voice-mode {
				width: calc(100% - 2rpx);
				height: 68rpx;
				border-radius: 70rpx;
				border: solid 1rpx #cdcdcd;
				display: flex;
				justify-content: center;
				align-items: center;
				font-size: 28rpx;
				background-color: #fff;
				color: #555;

				&.recording {
					background-color: #e5e5e5;
				}
			}

			.text-mode {
				width: 100%;
				min-height: 70rpx;
				display: flex;
				background-color: #F1F1F1;
				border-radius: 40rpx;

				.box {
					width: 100%;
					padding-left: 30rpx;
					min-height: 70rpx;
					display: flex;
					align-items: center;

					textarea {
						width: 100%;
						height: 70rpx;
					}
				}

				.em {
					flex-shrink: 0;
					width: 80rpx;
					padding-left: 10rpx;
					height: 70rpx;
					display: flex;
					justify-content: center;
					align-items: center;
				}
			}
		}
	}

	.keyboard {
		transition: all 0.2s;
	}

	.record {
		width: 40vw;
		height: 40vw;
		position: fixed;
		top: 55%;
		left: 30%;
		background-color: rgba(0, 0, 0, .6);
		border-radius: 20rpx;

		.ing {
			width: 100%;
			height: 30vw;
			display: flex;
			justify-content: center;
			align-items: center;

			// 模拟录音音效动画
			@keyframes volatility {
				0% {
					background-position: 0% 130%;
				}

				20% {
					background-position: 0% 150%;
				}

				30% {
					background-position: 0% 155%;
				}

				40% {
					background-position: 0% 150%;
				}

				50% {
					background-position: 0% 145%;
				}

				70% {
					background-position: 0% 150%;
				}

				80% {
					background-position: 0% 155%;
				}

				90% {
					background-position: 0% 140%;
				}

				100% {
					background-position: 0% 135%;
				}
			}

			.icon {
				background-image: linear-gradient(to bottom, #f09b37, #fff 50%);
				background-size: 100% 200%;
				animation: volatility 1.5s ease-in-out -1.5s infinite alternate;
				-webkit-background-clip: text;
				-webkit-text-fill-color: transparent;
				font-size: 150rpx;
				color: #f09b37;
			}
		}

		.cancel {
			width: 100%;
			height: 30vw;
			display: flex;
			justify-content: center;
			align-items: center;

			.icon {
				color: #fff;
				font-size: 150rpx;
			}
		}

		.tis {
			width: 100%;
			height: 10vw;
			display: flex;
			justify-content: center;
			font-size: 28rpx;
			color: #fff;

			&.change {
				color: #f09b37;
			}
		}
	}

	.content {
		width: 100%;
		height: 100vh;
		background: linear-gradient(180deg, #fff 0%, #EEF5FF 100%);

		.navbar {
			.robot {
				width: 37rpx;
				height: 33rpx;
				margin: 0 20rpx;
			}
		}

		.opetionBox {
			background-color: #fff;
			padding: 48rpx 24rpx 54rpx;

			.opetionText {
				font-weight: 400;
				font-size: 20rpx;
				color: #333333;
				margin-top: 16rpx;
			}
		}

		.msgBox {
			position: relative;
			flex: 1;
			border-radius: 30rpx 30rpx 0px 0px;
			background: linear-gradient(180deg, #F2F2F2 0%, #EEF5FF 100%);
			// margin-top:-20rpx;
		}

		.msg-list {
			background: transparent;
			width: 96%;
			position: absolute;
			top: 0;
			bottom: 20rpx;

			.loading {
				//loading动画
				display: flex;
				justify-content: center;

				@keyframes stretchdelay {

					0%,
					40%,
					100% {
						transform: scaleY(0.6);
					}

					20% {
						transform: scaleY(1.0);
					}
				}

				.spinner {
					margin: 20rpx 0;
					width: 60rpx;
					height: 100rpx;
					display: flex;
					align-items: center;
					justify-content: space-between;

					view {
						background-color: #2F80ED;
						height: 50rpx;
						width: 6rpx;
						border-radius: 6rpx;
						animation: stretchdelay 1.2s infinite ease-in-out;
					}

					.rect2 {
						animation-delay: -1.1s;
					}

					.rect3 {
						animation-delay: -1.0s;
					}

					.rect4 {
						animation-delay: -0.9s;
					}

					.rect5 {
						animation-delay: -0.8s;
					}
				}
			}

			.row {
				&:first-child {
					margin-top: 20rpx;
				}

				padding: 20rpx 0;

				.my .left,
				.other .right {
					width: 100%;
					display: flex;

					.bubble {
						padding: 14rpx 24rpx;
						font-weight: 400;
						font-size: 26rpx;
						color: #333333;
						word-break: break-word;

						&.img {
							background-color: transparent;
							padding: 0;
							overflow: hidden;

							image {
								max-width: 350rpx;
								max-height: 350rpx;
							}
						}

						&.voice {
							.icon {
								font-size: 40rpx;
								display: flex;
								align-items: center;
							}

							.icon:after {
								content: " ";
								width: 53rpx;
								height: 53rpx;
								border-radius: 100%;
								position: absolute;
								box-sizing: border-box;
							}

							.length {
								font-size: 28rpx;
							}
						}
					}
				}

				.my .right,
				.other .left {
					flex-shrink: 0;

					image {
						width: 68rpx;
						height: 68rpx;
						border-radius: 50%;
					}
				}

				.my {
					width: 100%;
					display: flex;
					justify-content: flex-end;

					.left {
						min-height: 80rpx;
						align-items: center;
						justify-content: flex-end;

						.bubble {
							border-radius: 16rpx 0 16rpx 16rpx;
							background-color: #fff;
							font-size: 26rpx;
							color: #333333;

							&.voice {
								.icon {}

								.length {
									margin-right: 20rpx;
								}
							}

							&.play {
								@keyframes my-play {
									0% {
										transform: translateX(80%);
									}

									100% {
										transform: translateX(0%);
									}
								}

								.icon:after {
									border-left: solid 10rpx rgba(240, 108, 122, .5);
									animation: my-play 1s linear infinite;
								}
							}
						}
					}

					.right {
						width: 68rpx;
						height: 68rpx;
						border-radius: 50%;
						margin-left: 16rpx;
					}
				}

				.other {
					width: 100%;
					display: flex;

					.left {
						width: 68rpx;
						height: 68rpx;
						border-radius: 50%;
						margin-right: 16rpx;
					}

					.right {
						flex-wrap: wrap;

						.username {
							width: 100%;
							height: 45rpx;
							font-size: 24rpx;
							color: #999;
							display: flex;

							.name {
								margin-right: 50rpx;
							}
						}

						.bubble {
							border-radius: 0px 16rpx 16rpx 16rpx;
							background-color: #fff;
							color: #333;

							&.voice {
								.icon {
									color: #333;

								}

								.length {
									margin-left: 20rpx;
								}
							}

							&.play {
								@keyframes other-play {
									0% {
										transform: translateX(-80%);
									}

									100% {
										transform: translateX(0%);
									}
								}

								.icon:after {
									border-right: solid 10rpx rgba(255, 255, 255, .8);

									animation: other-play 1s linear infinite;
								}
							}
						}
					}
				}
			}
		}
	}

	.onlyTextBox {
		max-width: 80%;
	}

	.cardBox {
		width: 70%;

		.cardTit {
			font-weight: 400;
			font-size: 30rpx;
			color: #333333;
			margin-bottom: 24rpx;
		}

		.top {
			padding-bottom: 18rpx;
			border-bottom: 1rpx solid #ededed;

			.photo-box {
				position: relative;

				.photo {
					width: 100rpx;
					height: 100rpx;
					border-radius: 50%;
					margin-right: 16rpx;
				}
			}

			.box1 {
				margin-bottom: 9rpx;

				.title {
					width: 46%;
					overflow: hidden;
					/* 超出部分隐藏 */
					text-overflow: ellipsis;
					/* 超出部分用省略号显示 */
					white-space: nowrap;
					/* 强制文本在一行内显示 */
					font-size: 32rpx;
					font-weight: 500;
					color: #333333;
					margin-right: 8rpx;
				}

				.real-name {
					background: #ffeae6;
					border-radius: 17px;
					border: 1px solid #ff6a47;
					// padding: 4rpx 18rpx;
					// margin-left: 8rpx;
					display: flex;
					justify-content: center;
					align-items: center;
					width: 116rpx;
					height: 34rpx;

					image {
						width: 20rpx;
						height: 20rpx;
						margin-right: 8rpx;
					}

					.text1 {
						font-weight: 500;
						font-size: 22rpx;
						color: #ff6a47;
					}
				}

				.sign-contract {
					background: #e5f0ff;
					border-radius: 17px;
					border: 1px solid #2f80ed;
					// padding: 4rpx 18rpx;
					margin-left: 8rpx;
					display: flex;
					align-items: center;
					justify-content: center;
					width: 116rpx;
					height: 34rpx;

					image {
						width: 20rpx;
						height: 20rpx;
						margin-right: 8rpx;
					}

					.text1 {
						font-weight: 500;
						font-size: 22rpx;
						color: #2f80ed;
					}
				}

				.distance-box {
					display: flex;
					align-items: center;

					.location {
						width: 20rpx;
						height: 20rpx;
						margin-right: 8rpx;
					}

					.text1 {
						font-weight: 400;
						font-size: 24rpx;
						color: #666666;
					}
				}
			}

			.box2 {
				.text1 {
					font-size: 24rpx;
					color: #999999;
				}

				.text2 {
					font-size: 24rpx;
					color: #2f80ed;
				}
			}
		}

		.box3 {
			align-items: flex-start;
			/* 顶部对齐 */
			width: 100%;
			margin-top: 16rpx;

			.text1 {
				font-size: 28rpx;
				color: #666666;
				flex-shrink: 0;
				/* 防止标签被压缩 */
			}

			.con {
				flex: 1;
				display: flex;
				flex-wrap: wrap;
				/* 关键属性：允许换行 */
				gap: 10rpx;
				/* 项目间距 */
				margin-left: 20rpx;

				.empty-text {
					font-size: 28rpx;
					color: #666666;
					flex-shrink: 0;
					/* 防止标签被压缩 */
				}

				.text2 {
					font-size: 28rpx;
					color: #333333;
				}

				.project {
					color: #2f80ed;
					font-size: 24rpx;
					font-weight: 500;
					background: #e5f0ff;
					padding: 6rpx 10rpx;
					margin-right: 14rpx;
					border-radius: 4rpx;
					white-space: nowrap;
					/* 单行显示 */
				}
			}
		}

		.footer {
			width: 100%;
			margin: 20rpx 0;
			gap: 16rpx;

			.btn {
				flex: 1;
				height: 56rpx;
				line-height: 56rpx;
				font-weight: 500;
				font-weight: 400;
				font-size: 24rpx;
				color: #2F80ED;
				border-radius: 28px;
				border: 1px solid #2F80ED;
				text-align: center;
			}
		}
	}

	.addressBox {
		width: 70%;
		border-radius: 16rpx 0 16rpx 16rpx;
		background-color: #fff;

		.map-container {
			width: 100%;
			height: 168rpx;
		}

		.address-text {
			padding: 8rpx 22rpx;

			.name {
				font-weight: bold;
				font-size: 30rpx;
				color: #333333;
				overflow: hidden;
				/* 超出部分隐藏 */
				text-overflow: ellipsis;
				/* 超出部分用省略号显示 */
				white-space: nowrap;
				/* 强制文本在一行内显示 */
			}

			.address {
				font-weight: 500;
				font-size: 22rpx;
				color: #666;
				overflow: hidden;
				/* 超出部分隐藏 */
				text-overflow: ellipsis;
				/* 超出部分用省略号显示 */
				white-space: nowrap;
				/* 强制文本在一行内显示 */
			}
		}
	}

	.orderBox {
		width: 80%;

		.cardTit {
			font-weight: 400;
			font-size: 30rpx;
			color: #333333;
			margin-bottom: 24rpx;
		}

		.order {
			margin: 19rpx 0 24rpx;

			image {
				width: 80rpx;
				height: 80rpx;
			}

			.info {
				flex: 1;
				margin-left: 16rpx;

				.title {
					font-weight: bold;
					font-size: 30rpx;
					color: #333333;
					max-width: 300rpx;
					white-space: nowrap;
					text-overflow: ellipsis;
					overflow: hidden;
				}

				.price {
					font-weight: bold;
					font-size: 30rpx;
					color: #333333;

					.unit {
						font-size: 20rpx;
					}
				}

				.des {
					font-weight: 400;
					font-size: 24rpx;
					color: #999999;
					margin-top: 5rpx;
					max-width: 350rpx;
					white-space: nowrap;
					text-overflow: ellipsis;
					overflow: hidden;
				}

				.num {
					font-size: 28rpx;
					color: #666666;
				}
			}
		}

		.orderbottom {
			border-top: 1px solid #E2E2E2;
			text-align: right;

			.orderno {
				margin: 15rpx 0;
				font-weight: 400;
				font-size: 24rpx;
				color: #333333;
			}

			.orderprice {
				font-weight: 400;
				font-size: 24rpx;
				color: #666666;

				.unit {
					font-size: 20rpx;
					font-weight: bold;
					margin-left: 16rpx;
				}

				.total {
					font-size: 30rpx;
					font-weight: bold;
				}
			}
		}

		.btn {
			width: 100%;
			border-radius: 28rpx;
			border: 2rpx solid #2F80ED;
			padding: 12rpx 0;
			text-align: center;
			font-weight: 400;
			font-size: 24rpx;
			color: #2F80ED;
			margin-top: 24rpx;
		}
	}
</style>